#pragma once
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.hpp"
class Sock
{
private:
    const static int backlog = 20;
public:
    //Sock(){}
    //初始化套接字
    int Socket()
    {
        //SOCK_STREAM tcp通信协议
        int listen_sock = socket(AF_INET,SOCK_STREAM,0);
        if(listen_sock >= 0 )
        {
            LogMessage(NORMAL,"create socket succseeful");
        }
        else
        {
            LogMessage(FATAL,"create sockt fail %d:%s",errno,strerror(errno));
            exit(1);
        }
        //设置端口复用
		int opt = 1;
		setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        return listen_sock;
    }

    //绑定ip和端口
    bool Bind(int socket,uint16_t port,std::string ip="")
    {
        struct sockaddr_in src;
        memset(&src,0,sizeof(src));
        src.sin_family = AF_INET;
        src.sin_port = htons(port);
        src.sin_addr.s_addr = ip.empty() ?  INADDR_ANY : inet_addr(ip.c_str());

        int bind_ret = bind(socket,(struct sockaddr*)&src,sizeof(src));
        if(bind_ret == -1)
        {
            LogMessage(FATAL,"bind fail %d:%s",errno,strerror(errno));
            exit(2);
        }
        LogMessage(NORMAL,"bind succseeful");
        return true;
    }
    //设置监听转态
    bool Listen(int socket)
    {
        int listen_ret = listen(socket,backlog);
        if(listen_ret == -1)
        {
            LogMessage(FATAL,"listen fail %d:%s",errno,strerror(errno));
            exit(3);
        }
        LogMessage(NORMAL,"listen succseeful");
        return true;
    }
    //获取新连接
    int Accept(int socket,std::string* ip,uint16_t* port)
    {
        struct sockaddr_in src;
        socklen_t len = sizeof(src);
        int accept_ret = accept(socket,(struct sockaddr*)&src,&len);
        if(accept_ret < 0 )
        {
            LogMessage(FATAL,"accept fail %d:%s",errno,strerror(errno));
            return -1;
        }
        *ip = inet_ntoa(src.sin_addr);
        *port = ntohs(src.sin_port);
        return accept_ret;
    }
    //建立连接
    bool Connect(int socket,std::string ip,uint16_t port)
    {
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(port);
        server.sin_addr.s_addr = inet_addr(ip.c_str());
        int connect_ret = connect(socket,(struct sockaddr*)&server,sizeof(server));

        if(connect_ret < 0)
        {
            LogMessage(FATAL,"connect fail %d:%s",errno,strerror(errno));
            exit(5);
        }
        return true;
    }
    ~Sock()
    {}
};